#coding:utf-8
'''
@author:        dayan
@date:          2021.07.19
@brief:         分页控件
@note:          移植自https://www.cnblogs.com/roadbike/p/5768514.html
@note:          感谢原作者
'''

import typing
from PySide6.QtGui import QIntValidator, QKeyEvent
from UIComponents.PageNavigatorUI import Ui_PageNavigator
from typing import Optional
from PySide6.QtWidgets import QHBoxLayout, QLabel, QWidget
from PySide6.QtCore import QEvent, QObject, Qt, Signal


class PageNavigator(QWidget, Ui_PageNavigator):
    currentPageChanged = Signal(int)

    def __init__(self, blockSize: int = 3, parent: Optional[QWidget] = None, f: Qt.WindowFlags = Qt.Tool) -> None:
        super().__init__(parent=parent, f=f)
        self.setupUi(self)
        self.__m_blockSize = 3
        self.__m_maxPage = 10
        self.__m_currentPage = 1
        self.__m_pageLabels = None
        self.setBlockSize(blockSize)
        self.initialize()

        self.setMaxPage(1)
        qss = ".QLabel[page=\"true\"] { padding: 6px; }" \
            + ".QLabel[currentPage=\"true\"] { color: rgb(190, 0, 0);}" \
            + ".QLabel[page=\"true\"]:hover { color: white; border-radius: 4px; background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(53, 121, 238, 255), stop:1 rgba(0, 202, 237, 255));}"
        self.setStyleSheet(qss)


    def eventFilter(self, watched: QObject, e: QEvent):
        if e.type() == QEvent.MouseButtonRelease:
            page = -1
            if watched == self.previousPageLabel:
                page = self.getCurrentPage() - 1
            
            if watched == self.nextPageLabel:
                page = self.getCurrentPage() + 1
            
            for i in range(0, len(self.__m_pageLabels)):
                if watched == self.__m_pageLabels[i]:
                    page = int(self.__m_pageLabels[i].text())
                    break
            
            if -1 != page:
                if len(self.pageLineEdit.text()) != 0:
                    self.pageLineEdit.clear()
                self.setCurrentPage(page, True)
                return True

        if watched == self.pageLineEdit and e.type() == QEvent.KeyRelease:
            ke = typing.cast(QKeyEvent, e)
            if ke.key() == Qt.Key_Enter or ke.key() == Qt.Key_Return:
                self.setCurrentPage(int(self.pageLineEdit.text()), True)
                return True

        # return self.eventFilter(watched, e)
        return False

    
    def getBlockSize(self):
        return self.__m_blockSize
    
    def getMaxPage(self):
        return self.__m_maxPage

    def getCurrentPage(self):
        return self.__m_currentPage

    def setMaxPage(self, page):
        page = [page, 1][1 > page]

        if self.__m_maxPage != page:
            self.__m_maxPage = page
            self.__m_currentPage = 1
            self.updatePageLabels()

    def setCurrentPage(self, page, signalEmitted = False):
        page = [page, 1][1 > page]
        page = [self.__m_maxPage, page][self.__m_maxPage > page]

        if page != self.__m_currentPage:
            self.__m_currentPage = page
            self.updatePageLabels()

            if signalEmitted:
                self.currentPageChanged.emit(page)

    # 为了便于计算, block size 必须是奇数, 且最小为3
    def setBlockSize(self, blockSize):
        blockSize = [blockSize, 3][3 > blockSize]
        if blockSize % 2 == 0:
            ++blockSize
        self.__m_blockSize = blockSize

    # 初始化页码的labels
    # 分成三个部分, 左...中...右
    def initialize(self):
        self.pageLineEdit.installEventFilter(self)
        self.pageLineEdit.setValidator(QIntValidator(1, 10000000, self))
        
        self.nextPageLabel.setProperty("page", "true")
        self.previousPageLabel.setProperty("page", "true")
        self.nextPageLabel.installEventFilter(self)
        self.previousPageLabel.installEventFilter(self)

        self.__m_pageLabels = []

        leftLayout = QHBoxLayout()
        centerLayout = QHBoxLayout()
        rightLayout = QHBoxLayout()
        leftLayout.setContentsMargins(0, 0, 0, 0)
        leftLayout.setSpacing(0)
        centerLayout.setContentsMargins(0, 0, 0, 0)
        centerLayout.setSpacing(0)
        rightLayout.setContentsMargins(0, 0, 0, 0)
        rightLayout.setSpacing(0)

        for i in range(0, self.__m_blockSize * 3):
            label = QLabel(str(i + 1), self)
            label.setProperty("page", "true")
            label.installEventFilter(self)

            self.__m_pageLabels.append(label)

            if i < self.__m_blockSize:
                leftLayout.addWidget(label)
            elif i < self.__m_blockSize * 2:
                centerLayout.addWidget(label)
            else:
                rightLayout.addWidget(label)
        
        self.leftPagesWidget.setLayout(leftLayout)
        self.centerPagesWidget.setLayout(centerLayout)
        self.rightPagesWidget.setLayout(rightLayout)

    def updatePageLabels(self):
        self.leftSeparateLabel.hide()
        self.rightSeparateLabel.hide()

        if self.__m_maxPage <= self.__m_blockSize * 3:
            for i in range(0, len(self.__m_pageLabels)):
                label = self.__m_pageLabels[i]
                if i < self.__m_maxPage:
                    label.setText(str(i + 1))
                    label.show()
                else:
                    label.hide()

                if self.__m_currentPage - 1 == i:
                    label.setProperty("currentPage", "true")
                else:
                    label.setProperty("currentPage", "false")
                
                label.setStyleSheet("/**/")
            return
        
        # 以下情况为maxPageNumber大于blockSize * 3, 所有的页码label都要显示
        # c 为 currentPage
        # n 为 block size
        # m 为 maxPage

        # 1. c ∈ [1, n + n/2 + 1]: 显示前 n * 2 个, 后 n 个: 只显示右边的分隔符
        # 2. c ∈ [m - n - n/2, m]: 显示前 n 个, 后 n * 2 个: 只显示左边的分隔符
        # 3. 显示[1, n], [c - n/2, c + n/2], [m - 2*n + 1, m]: 两个分隔符都显示

        c = self.__m_currentPage
        n = self.__m_blockSize
        m = self.__m_maxPage
        centerStartPage = 0
        if c >= 1 and c < n + n / 2 + 1:
            # 1. c ∈ [1, n + n/2 + 1]: 显示前 n * 2 个, 后 n 个: 只显示右边的分隔符
            centerStartPage = n + 1
            self.rightSeparateLabel.show()
        elif c >= m - n - n / 2 and c <= m:
            # 2. c ∈ [m - n - n/2, m]: 显示前 n 个, 后 n * 2 个: 只显示左边的分隔符
            centerStartPage = m - n - n + 1
            self.leftSeparateLabel.show()
        else:
            # 3. 显示[1, n], [c - n/2, c + n/2], [m - n + 1, m]: 两个分隔符都显示
            centerStartPage = c - n / 2
            self.rightSeparateLabel.show()
            self.leftSeparateLabel.show()

        for i in range(0, n):
            self.__m_pageLabels[i].setText(str(i + 1))
            self.__m_pageLabels[n + i].setText(str(centerStartPage + i))
            self.__m_pageLabels[3 * n - i - 1].setText(str(m - i))

        for i in range(0, len(self.__m_pageLabels)):
            label = self.__m_pageLabels[i]
            page = int(label.text())
            if page == self.__m_currentPage:
                label.setProperty("currentPage", "true")
            else:
                label.setProperty("currentPage", "false")

            label.setStyleSheet("/**/")
            label.show()
